#!/usr/bin/env python3
"""
生产管理API
提供生产任务相关的CRUD操作和状态管理功能
"""

from typing import List, Optional
from datetime import datetime, timedelta
from enum import Enum
from fastapi import APIRouter, Depends, HTTPException, Query
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.orm import selectinload
from sqlmodel import select, and_, or_
from database.connection import get_session
from database.models import ProductionJob, Order, Manufacturer, Model3D, OrderStatus
from validators.order_validator import ProductionJobCreate, ProductionJobUpdate
from services.shopify_service import ShopifyService


class ProductionStatus(str, Enum):
    """生产状态枚举"""
    PENDING = "pending"  # 待处理
    ASSIGNED = "assigned"  # 已分配
    IN_PROGRESS = "in_progress"  # 生产中
    QUALITY_CHECK = "quality_check"  # 质检中
    COMPLETED = "completed"  # 已完成
    FAILED = "failed"  # 失败


router = APIRouter(prefix="/api/production", tags=["生产管理"])


@router.get("/jobs", response_model=List[dict])
async def get_production_jobs(
    skip: int = 0,
    limit: int = 100,
    status: Optional[ProductionStatus] = None,
    manufacturer_id: Optional[int] = None,
    order_id: Optional[int] = None,
    priority: Optional[int] = None,
    start_date: Optional[datetime] = None,
    end_date: Optional[datetime] = None,
    search: Optional[str] = Query(None, description="搜索订单号或厂商名称"),
    session: AsyncSession = Depends(get_session)
):
    """获取生产任务列表"""
    query = select(ProductionJob).options(
        selectinload(ProductionJob.order),
        selectinload(ProductionJob.manufacturer)
    )
    
    # 应用筛选条件
    if status:
        query = query.where(ProductionJob.status == status)
    
    if manufacturer_id:
        query = query.where(ProductionJob.manufacturer_id == manufacturer_id)
    
    if order_id:
        query = query.where(ProductionJob.order_id == order_id)
    
    if priority:
        query = query.where(ProductionJob.priority == priority)
    
    if start_date:
        query = query.where(ProductionJob.created_at >= start_date)
    
    if end_date:
        query = query.where(ProductionJob.created_at <= end_date)
    
    if search:
        query = query.join(Order).join(Manufacturer).where(
            or_(
                Order.order_number.contains(search),
                Manufacturer.company_name.contains(search)
            )
        )
    
    # 排序和分页
    query = query.order_by(ProductionJob.priority.desc(), ProductionJob.created_at.desc())
    query = query.offset(skip).limit(limit)
    
    result = await session.execute(query)
    jobs = result.scalars().all()
    
    return [job.dict() for job in jobs]


@router.get("/jobs/{job_id}", response_model=dict)
async def get_production_job(
    job_id: int,
    session: AsyncSession = Depends(get_session)
):
    """获取单个生产任务详情"""
    result = await session.execute(
        select(ProductionJob)
        .options(
            selectinload(ProductionJob.order),
            selectinload(ProductionJob.manufacturer)
        )
        .where(ProductionJob.id == job_id)
    )
    job = result.scalar_one_or_none()
    
    if not job:
        raise HTTPException(status_code=404, detail="生产任务不存在")
    
    return job.dict()


@router.post("/jobs", response_model=dict)
async def create_production_job(
    job_data: ProductionJobCreate,
    session: AsyncSession = Depends(get_session)
):
    """创建生产任务"""
    # 检查订单是否存在
    result = await session.execute(select(Order).where(Order.id == job_data.order_id))
    order = result.scalar_one_or_none()
    
    if not order:
        raise HTTPException(status_code=400, detail="订单不存在")
    
    # 检查厂商是否存在
    result = await session.execute(select(Manufacturer).where(Manufacturer.id == job_data.manufacturer_id))
    manufacturer = result.scalar_one_or_none()
    
    if not manufacturer:
        raise HTTPException(status_code=400, detail="厂商不存在")
    
    # 检查3D模型是否存在（如果提供）
    if job_data.model_3d_id:
        result = await session.execute(select(Model3D).where(Model3D.id == job_data.model_3d_id))
        model_3d = result.scalar_one_or_none()
        
        if not model_3d:
            raise HTTPException(status_code=400, detail="3D模型不存在")
    
    # 创建生产任务
    job = ProductionJob(
        order_id=job_data.order_id,
        manufacturer_id=job_data.manufacturer_id,
        model_3d_id=job_data.model_3d_id,
        quantity=job_data.quantity,
        priority=job_data.priority,
        status=ProductionStatus.PENDING,
        estimated_completion_date=job_data.estimated_completion_date,
        material_requirements=job_data.material_requirements,
        production_notes=job_data.production_notes,
        quality_requirements=job_data.quality_requirements,
        cost_estimate=job_data.cost_estimate
    )
    
    session.add(job)
    
    # 更新订单状态为生产中
    order.status = OrderStatus.PRODUCTION
    order.status_updated_at = datetime.utcnow()
    session.add(order)
    
    await session.commit()
    await session.refresh(job)
    
    return job.dict()


@router.put("/jobs/{job_id}", response_model=dict)
async def update_production_job(
    job_id: int,
    job_update: ProductionJobUpdate,
    session: AsyncSession = Depends(get_session)
):
    """更新生产任务信息"""
    result = await session.execute(
        select(ProductionJob).where(ProductionJob.id == job_id)
    )
    job = result.scalar_one_or_none()
    
    if not job:
        raise HTTPException(status_code=404, detail="生产任务不存在")
    
    # 更新字段
    update_data = job_update.dict(exclude_unset=True)
    
    for field, value in update_data.items():
        setattr(job, field, value)
    
    # 如果状态改变，更新状态时间
    if 'status' in update_data:
        job.status_updated_at = datetime.utcnow()
        
        # 如果状态变为已完成
        if update_data['status'] == ProductionStatus.COMPLETED:
            job.completed_at = datetime.utcnow()
            job.actual_completion_date = datetime.utcnow()
            
            # 检查是否所有生产任务都已完成
            result = await session.execute(
                select(ProductionJob)
                .where(ProductionJob.order_id == job.order_id)
                .where(ProductionJob.status != ProductionStatus.COMPLETED)
            )
            other_jobs = result.scalars().all()
            
            if not other_jobs:
                # 所有任务都已完成，更新订单状态
                result = await session.execute(select(Order).where(Order.id == job.order_id))
                order = result.scalar_one_or_none()
                if order:
                    order.status = OrderStatus.SHIPPED
                    order.status_updated_at = datetime.utcnow()
                    order.shipped_at = datetime.utcnow()
                    session.add(order)
        
        # 如果状态变为质检中
        elif update_data['status'] == ProductionStatus.QUALITY_CHECK:
            job.quality_check_started_at = datetime.utcnow()
    
    job.updated_at = datetime.utcnow()
    
    await session.commit()
    await session.refresh(job)
    
    return job.dict()


@router.put("/jobs/{job_id}/status")
async def update_production_job_status(
    job_id: int,
    status: ProductionStatus,
    notes: Optional[str] = None,
    session: AsyncSession = Depends(get_session)
):
    """更新生产任务状态"""
    result = await session.execute(
        select(ProductionJob).where(ProductionJob.id == job_id)
    )
    job = result.scalar_one_or_none()
    
    if not job:
        raise HTTPException(status_code=404, detail="生产任务不存在")
    
    old_status = job.status
    job.status = status
    job.status_updated_at = datetime.utcnow()
    
    if notes:
        job.production_notes = f"{job.production_notes or ''}\n状态更新: {old_status} -> {status}\n备注: {notes}"
    
    # 根据状态更新相关时间
    if status == ProductionStatus.IN_PROGRESS:
        job.started_at = datetime.utcnow()
    elif status == ProductionStatus.COMPLETED:
        job.completed_at = datetime.utcnow()
        job.actual_completion_date = datetime.utcnow()
    elif status == ProductionStatus.QUALITY_CHECK:
        job.quality_check_started_at = datetime.utcnow()
    elif status == ProductionStatus.CANCELLED:
        job.cancelled_at = datetime.utcnow()
    
    await session.commit()
    await session.refresh(job)
    
    return job.dict()


@router.put("/jobs/{job_id}/progress")
async def update_production_progress(
    job_id: int,
    progress_percentage: int,
    notes: Optional[str] = None,
    session: AsyncSession = Depends(get_session)
):
    """更新生产进度"""
    result = await session.execute(
        select(ProductionJob).where(ProductionJob.id == job_id)
    )
    job = result.scalar_one_or_none()
    
    if not job:
        raise HTTPException(status_code=404, detail="生产任务不存在")
    
    if progress_percentage < 0 or progress_percentage > 100:
        raise HTTPException(status_code=400, detail="进度百分比必须在0-100之间")
    
    job.progress_percentage = progress_percentage
    job.updated_at = datetime.utcnow()
    
    if notes:
        job.production_notes = f"{job.production_notes or ''}\n进度更新: {progress_percentage}%\n备注: {notes}"
    
    # 如果进度达到100%，自动更新状态为已完成
    if progress_percentage == 100 and job.status != ProductionStatus.COMPLETED:
        job.status = ProductionStatus.COMPLETED
        job.completed_at = datetime.utcnow()
        job.actual_completion_date = datetime.utcnow()
        job.status_updated_at = datetime.utcnow()
    
    await session.commit()
    await session.refresh(job)
    
    return job.dict()


@router.delete("/jobs/{job_id}")
async def delete_production_job(
    job_id: int,
    session: AsyncSession = Depends(get_session)
):
    """删除生产任务（仅未开始任务可删除）"""
    result = await session.execute(
        select(ProductionJob).where(ProductionJob.id == job_id)
    )
    job = result.scalar_one_or_none()
    
    if not job:
        raise HTTPException(status_code=404, detail="生产任务不存在")
    
    # 检查是否可以删除（仅未开始任务可删除）
    if job.status not in [ProductionStatus.PENDING, ProductionStatus.CANCELLED]:
        raise HTTPException(status_code=400, detail="只有未开始或已取消的任务可以删除")
    
    await session.delete(job)
    await session.commit()
    
    return {"message": "生产任务删除成功"}


@router.get("/stats/production")
async def get_production_dashboard(
    start_date: Optional[datetime] = None,
    end_date: Optional[datetime] = None,
    session: AsyncSession = Depends(get_session)
):
    """获取生产统计仪表板数据"""
    query = select(ProductionJob)
    
    # 时间范围筛选
    if start_date:
        query = query.where(ProductionJob.created_at >= start_date)
    
    if end_date:
        query = query.where(ProductionJob.created_at <= end_date)
    
    result = await session.execute(query)
    jobs = result.scalars().all()
    
    # 统计信息
    total_jobs = len(jobs)
    
    status_counts = {}
    priority_counts = {}
    
    for job in jobs:
        # 状态统计
        status = job.status.value
        status_counts[status] = status_counts.get(status, 0) + 1
        
        # 优先级统计
        priority = job.priority
        priority_counts[priority] = priority_counts.get(priority, 0) + 1
    
    # 计算完成率
    completed_jobs = status_counts.get(ProductionStatus.COMPLETED.value, 0)
    completion_rate = (completed_jobs / total_jobs * 100) if total_jobs > 0 else 0
    
    # 获取延期任务
    overdue_jobs = []
    for job in jobs:
        if job.status not in [ProductionStatus.COMPLETED, ProductionStatus.CANCELLED]:
            if job.estimated_completion_date and job.estimated_completion_date < datetime.utcnow():
                overdue_jobs.append(job)
    
    return {
        "total_jobs": total_jobs,
        "status_counts": status_counts,
        "priority_counts": priority_counts,
        "completion_rate": round(completion_rate, 2),
        "overdue_jobs_count": len(overdue_jobs),
        "overdue_jobs": [job.dict() for job in overdue_jobs[:10]]  # 只返回前10个
    }


@router.get("/manufacturers/{manufacturer_id}/jobs")
async def get_manufacturer_jobs(
    manufacturer_id: int,
    status: Optional[ProductionStatus] = None,
    session: AsyncSession = Depends(get_session)
):
    """获取指定厂商的生产任务"""
    query = select(ProductionJob).options(
        selectinload(ProductionJob.order),
        selectinload(ProductionJob.model_3d)
    ).where(ProductionJob.manufacturer_id == manufacturer_id)
    
    if status:
        query = query.where(ProductionJob.status == status)
    
    query = query.order_by(ProductionJob.priority.desc(), ProductionJob.created_at.desc())
    
    result = await session.execute(query)
    jobs = result.scalars().all()
    
    return [job.dict() for job in jobs]


@router.post("/jobs/{job_id}/assign")
async def assign_production_job(
    job_id: int,
    manufacturer_id: int,
    priority: Optional[int] = None,
    notes: Optional[str] = None,
    session: AsyncSession = Depends(get_session)
):
    """分配生产任务给厂商"""
    result = await session.execute(
        select(ProductionJob).where(ProductionJob.id == job_id)
    )
    job = result.scalar_one_or_none()
    
    if not job:
        raise HTTPException(status_code=404, detail="生产任务不存在")
    
    # 检查厂商是否存在
    result = await session.execute(select(Manufacturer).where(Manufacturer.id == manufacturer_id))
    manufacturer = result.scalar_one_or_none()
    
    if not manufacturer:
        raise HTTPException(status_code=400, detail="厂商不存在")
    
    # 分配任务
    job.manufacturer_id = manufacturer_id
    if priority:
        job.priority = priority
    
    if notes:
        job.production_notes = f"{job.production_notes or ''}\n任务分配备注: {notes}"
    
    job.updated_at = datetime.utcnow()
    
    await session.commit()
    await session.refresh(job)
    
    return job.dict()